<?php
class unitree {
  function __construct() {
  }

  public function gettree() {
  
    $data = '[]';
	$errcode = 0;
	$errmess = '';
    try
    {
// Только зарегистрированные пользователи могут видеть данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);

		$rwd = $_SESSION['priv']->units->rwd;
		if( !$rwd  ) throw new Exception(ERR_M::DATA_ACC_DISABLED, 99);

		$tab_id = $_SESSION['priv']->units->id;
		
// Открываем базу данных
		$db = App::me()->dbOpen();	

        $rs = $db->query( "SELECT * FROM dtree WHERE dtr_tab_id = ${tab_id}" );
		$row = $rs->fetchObject();
		$data = $row->dtr_tree;
		$rs->closeCursor();
            
    }
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}
 
	if( $errcode ) {
		$unit = new stdClass;
		$unit->title = '';
		$unit->errcode = $errcode;
		$unit->errmess = $errmess;
		return json_encode(array($unit));
	}
	else return $data;
  }
  
  
  protected function findByKey( $ar, $skey ) {
	$success = false;
	for( $i=0; $i<count($ar); $i++ ) {
		$ob = $ar[$i];
		if( $ob->key == $skey ) {
			$success = true;
			break;
		}
		if( isset($ob->children) && is_array( $ob->children ) ) {
			$nob = $this->findByKey( $ob->children, $skey );
			if( $nob !== false ) {
				$ob = $nob;
				$success = true;
				break;
			}
		}
	}
	return $success ? $ob : false;
  }
  
  protected function getSubTreeByKey( &$ar ) {
	$res = array();
	for( $i=0; $i<count($ar); $i++ ) {
		$ob = $ar[$i];
		$res[] = $ob->key;
		if( isset($ob->children) && is_array( $ob->children ) ) {
			$res += $this->getSubTreeByKey( $ob->children );
		}
	}
	return $res;
  }
  
  public function insert() {

    $dtr_tree = isset($_POST['dtr_tree']) ? $_POST['dtr_tree'] : '';
    $dtr_okey = isset($_POST['dtr_okey']) ? $_POST['dtr_okey'] : '';
	
	$last_key = 0;
	$errcode = 0;
	$errmess = '';
    try
    {
// Только зарегистрированные пользователи могут вносить данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);
		$uni_user_id = $_SESSION['user_id'];
		
//Есть ли разрешение на вставку записей
		$rwd = $_SESSION['priv']->units->rwd;
		if( ($rwd & PERM_BITS::WRITE_OWN) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);

// Идентификатор таблицы (дерева группировок)
		$tab_id = $_SESSION['priv']->units->id;

// Все ли данные переданы
        if ( !$dtr_tree || !$dtr_okey )
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);
		
// Декодируем дерево и ищем ключ, который нужно заменить
		$odtr = json_decode( $dtr_tree );
		$ob = $this->findByKey( $odtr, $dtr_okey );
		if( $ob === false )
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);
		
// Открываем базу данных
		$db = App::me()->dbOpen();	

// Считываем данные для данного меню
		try {
			$db->beginTransaction();
			$rs = $db->query("SELECT dtr_last_key FROM dtree WHERE dtr_tab_id = ${tab_id} FOR UPDATE");                  
			$row = $rs->fetchObject();
			$last_key = $row->dtr_last_key + 1;
			$rs->closeCursor();
	
// Заменяем ключ в ранее найденном объекте и кодируем дерево
			$ob->key = strval($last_key);
			$dtr_tree = json_encode( $odtr );
			
// Пишем данные
			$sql =  "UPDATE dtree SET ".
						"dtr_last_key = ".$db->quote($last_key).", ".
						"dtr_tree = ".$db->quote($dtr_tree)." ".
					"WHERE dtr_tab_id = ${tab_id}";
					
			$db->exec($sql);
			$db->commit();
		}
		catch (PDOException $e) {
			$db->rollback(); 
			$errcode = 1;
			$errmess = ERR_M::DATABASE_ERROR;
		}		
    }
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}

	return array('errcode'=>$errcode,'errmess'=>$errmess,'key'=>strval($last_key));
  }

  public function update() {

    $dtr_tree = isset($_POST['dtr_tree']) ? $_POST['dtr_tree'] : '';
	
	$errcode = 0;
	$errmess = '';
    try
    {
// Только зарегистрированные пользователи могут вносить данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);
		$uni_user_id = $_SESSION['user_id'];
		
//Есть ли разрешение на вставку записей
		$rwd = $_SESSION['priv']->units->rwd;
		if( ($rwd & PERM_BITS::WRITE_ANY) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);

// Идентификатор таблицы (дерева группировок)
		$tab_id = $_SESSION['priv']->units->id;

// Все ли данные переданы
        if ( !$dtr_tree )
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);
		
// Открываем базу данных
		$db = App::me()->dbOpen();	
 			
// Пишем данные
		$sql =  "UPDATE dtree SET ".
					"dtr_tree = ".$db->quote($dtr_tree)." ".
				"WHERE dtr_tab_id = ${tab_id}";
				
		$db->exec($sql);
    }
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}

	return array('errcode'=>$errcode,'errmess'=>$errmess);
  }


  public function delete() {

    $dtr_tree = isset($_POST['dtr_tree']) ? $_POST['dtr_tree'] : '';
    $dtr_okey = isset($_POST['dtr_okey']) ? $_POST['dtr_okey'] : '';
	
	$errcode = 0;
	$errmess = '';
    try
    {
// Только зарегистрированные пользователи могут вносить данные
		if( !isset($_SESSION['user_id']) || $_SESSION['user_id'] == 0 )
			throw new Exception(ERR_M::TIMEOUT_ERROR, 999);
		$uni_user_id = $_SESSION['user_id'];
		
//Есть ли разрешение на вставку записей
		$rwd = $_SESSION['priv']->units->rwd;
		if( ($rwd & PERM_BITS::DELETE_ANY) == 0 ) throw new Exception(ERR_M::DATA_OPER_DISABLED, 99);

// Идентификатор таблицы (дерева группировок)
		$tab_id = $_SESSION['priv']->units->id;

// Все ли данные переданы
        if ( !$dtr_tree || !$dtr_okey )
			throw new Exception(ERR_M::PROTOCOL_ERROR, 1);
		
// Открываем базу данных
		$db = App::me()->dbOpen();	

// Считываем данные для данного меню
		try {
			$db->beginTransaction();
			$rs = $db->query("SELECT dtr_tree FROM dtree WHERE dtr_tab_id = ${tab_id} FOR UPDATE");                  
			$row = $rs->fetchObject();
			$odtr = json_decode($row->dtr_tree);
			$rs->closeCursor();
	
// Ищем ключ, который нужно удалить
			$ob = $this->findByKey( $odtr, $dtr_okey );
			if( $ob === false )
				throw new Exception("Подгруппа не найдена. Обновите дерево.", 1);
		
// Получить список подлежащих ключей.
			if( isset($ob->children) && is_array( $ob->children ) )	{		
				$akeys = $this->getSubTreeByKey( $ob->children );
			}
		
			$akeys[] = $dtr_okey;

// Проверяем, наличие материалов в удаляемых подгруппах
			$rs = $db->query("SELECT 1 FROM units WHERE uni_leaf_id IN ( ".implode(',',$akeys)." ) LIMIT 1");                  
			$row = $rs->fetchObject();
			if( $row )
				throw new Exception("В данной группе или ее подгруппах имеются материалы.", 1);
				
			$rs->closeCursor();
 			
// Пишем данные
			$sql =  "UPDATE dtree SET ".
						"dtr_tree = ".$db->quote($dtr_tree)." ".
					"WHERE dtr_tab_id = ${tab_id}";
					
			$db->exec($sql);
			$db->commit();
		}
		catch (PDOException $e) {
			$db->rollback(); 
			$errcode = 1;
			$errmess = ERR_M::DATABASE_ERROR;
		}		
		catch ( Exception $e ) {
			$db->rollback(); 
			$errcode = $e->getCode();
			$errmess = $e->getMessage();
		}
    }
	catch (PDOException $e) {
		$errcode = 1;
		$errmess = ERR_M::DATABASE_ERROR;
	}
    catch ( Exception $e ) {
		$errcode = $e->getCode();
		$errmess = $e->getMessage();
	}

	return array('errcode'=>$errcode,'errmess'=>$errmess);
  }

  public function move() {
	return $this->update();
  }
}
?>